<?
/*
	Бибилиотека методов для работы формы связи.
	
	TODO:
	- отображение в поля значения из URL (widget_mailform)
	- Цветовая схема (придумать, как легко сделать цветовую схему для шаблона диазйна) (mailform/templates/шаблоны дизайна)
	- доп. типы поля: ~ выпадающий список, ~ выпадающий список "Кому (email)", ~ галочка, радио-список (widget_settings mailform.php , шаблоны формы , send_mailform) 
	~ задаывать начальное значение (для списков или для строчного поля) - widget_settings mailform.php , widget_mailform (приоритеты: GET, POST, $field->value, default)
	


*/
class Mailform {

	// свойства обрабатываемой формы 
	static $params;
	static $form_period = 3600; //60*60 = 1час  -  макс. период действенности формы от момента её формирования, в течение которого принимаются данные от формы, в секундах 
	
	static $errors = array(); // массив ошибок для вывода в форме
	
	// вычисляет виджет "Форма связи" + отправляет данные
	static function widget_mailform($params)
	{
		self::$params = &$params;
		
		if (is_string($params)) parse_str($params, $params);
		
		// pr($params);
		
		// преобразуем  $params['fields'] (поля формы) к более удобной форме - массив объектов со свойствами полей  
		$params_fields = $params['fields'];
		$fields=array();
		foreach ($params_fields['label'] AS $i => $label) 
		{ 
			if (!$label) continue;
			
			$field = (object)array(
				'name' 		=> ($name = ('field'.($i+1))),
				'value' 	=> html(POST($name)),
				'label'		=> $label,
				'label_html'=> $label .':' . (val($params_fields['required'][$i])? '<font color=red><b class=mailform_requared title="обязательно для заполнения" >*</b></font>' : ''),
				
				'required' 	=> ($req   = val($params_fields['required'][$i])),
				'type'		=> ($type  = $params_fields['type'][$i]),
				
			);
			// подготавливаем HTML-код поля ввода  
			$field->field = self::field($field); 
			
			
			$fields[] = $field;
			
			if ($type =='textarea') $params['textarea_exists']=true;
			if ($type =='file') $params['file_exists']=true;
			if ($req) $params['required_exists']=true;
			
			
		}
		
		// добавляем в конце списка полей - каптчу
		// ???????
		// $fields[] = self::captcha();
		// pr($fields);
		
		$params['fields'] = $fields;
		
		//pr($params);
		
		// пытаемся отправить даныне из формы, и если данные не корректны, то сообщение об ошибке (строка) записываются в $params['error'] (для вывода на странице ) & $params['error_alert'] (для вывода внутри alert() ), а массив всех ошибок сохраняется в ассоциативный массив self::$params['errors'] c индексами - именами полей 
		$params['error'] = '';
		self::send_mailform($params);
		
		
		// обрабатываем шаблон формы и возвращаем готовую форму связи
		return eval_template($params['widget_template'], $params, array('params'=> $params));
	}
	

	// вычисляет начало формы связи + скрытые служебные поля
	static function start()
	{
		// ~TODO: проверять наличие шаблона 'mailform_start'
		
		//pr(self::$params);
		//self::$params['file_exists'];
		
		$uid= self::$params['widget_uid'];
		
		$result = "
			<FORM action='#$uid' id='$uid' method='post' enctype='multipart/form-data'  >
			<INPUT type=hidden name=widget_uid value='$uid' >
			";
		// action формы указывает на якорь самой формы ( #$uid ), чтобы в случае ошибки, страница скролилась сразу к форме, где и будет выведен текст ошибки. Поэтому в шаблоне формы связи вызов Mailfor::start() должен размещаться раньше чем вывод $error
		// widget_uid - уникальынй идентификатор виджета, фильтр для отбора POST запросов, предназначены только текущей форме 
		
		
		return $result;
	}
	
	
	// вычисляет все поля формы
	static function fields( $field_template)
	{
		// TODO: проверять наличие шаблона 'mailform_fields'
		
		// pr(self::$params['fields']);
		
		if(is_string($field_template))
			$field_template = array('default'=>$field_template);
		
		$result='';
		foreach (self::$params['fields'] as $field) 
		{
			if(empty($field->field))
				$field->field	= self::field($field);
			
			if ( !$field->label 
				  && !$field->field
				  ) continue;
			
			$template = val( $field_template[$field->type], 
							 $field_template['default']    ); 
			
			//pr_($field->type, $template, $field);
			$field->label = $field->label_html;
			$result.= macro_replaces($template, $field);
			// eval_phtml ...	
		}
		
		return $result;
	}
	
	// вычисляет и возвращает код для поля формы
	static function field ($field)
	{
		$code='';
		
		switch ($field->type)
		{
			case('text'):
				$code="<input class=input_text name='{$field->name}' value='{$field->value}' type=text maxlength=50>";
				break;
			 case('textarea'):
				$code="
					<div class=textarea_wrapper>
					<textarea name='{$field->name}'
					>{$field->value}</textarea>
					</div>
					";
				//$code="***";
				
				break;
			case('file'):
				$code="<input class=input_file type=file name='{$field->name}' >";
				break; 
			case('select'):
				$code="";
				break;
			case('checkbox'):
				$code="";
				break;
			case('radio'):
				$code="";
				break;
		}
		return $code;
	}
	
	
	// выводит кнопки формы - Отправить , Сброс
	static function submits($tpl_submits='')
	{	// TODO: проверять наличие шаблона 'mailform_submits'
	
		// вычисляем шаблон для "области кнопок"
		if(empty($tpl_submits))  $tpl_submits ="%submit% %reset%";
		
		// вычисляем коды для кнопок
		$submit = "<INPUT type=submit value=Отправить >"; 	
			//onclick="return checkForm(this.form);" 
		$reset 	= "<INPUT type=reset value=Сброс >";
		
		//pr($tpl_submits);
		
		// перед кнопками выводим каптчу (или скрытые поля)
		
		$result = '';
		$result .= 	Antispam::captcha( self::$params['widget_uid'] );
		$result .= 	str_replaces($tpl_submits, array(
										'%submit%'	=> $submit,  
										'%reset%'	=> $reset
									));
		// pr($result);
		
		return $result;	
	}
	
	// вычисляет завершение формы 
	static function end()
	{
		return "</FORM>";
	}
	

	
	/* self::send_mailform($params) -  Метод для отправки данных из формы. Вызывается из метода Mailform::widget_mailform .
	
		1. Убеждается что данные формы - не спам (фильтрует некорректные параметры POST и SERVER)
		2. Проверяет данные на правильность и если ошибка - создает сообщение об ошибке и возвращает к форме
		3. Вычисляет шаблоны и вычисляет послания из формы и письмо подтверждения для посетителя
		4. Выводит сообщение об успехе или редиректит на страницу с подтверждением
		 
		
	*/
	static function send_mailform()
	{
		$params = &self::$params;
		$fields = &self::$params['fields'];
		
		$params['errors'] =& self::$errors; // здесь запутанно...  надо как-то проще сделать
		$params['errors']='';
		
		// убеждаемся, что в форму нужно обрабатывать
		if (empty($_POST) || empty($_POST['widget_uid'])) return;
		// pr($_POST);
		// pr($fields);
		
		
		// убеждаемся, что данные переданы именно в эту форму 
		if ($params['widget_uid']!=POST('widget_uid')) return;
		
		
		// TODO: сделать обработку ошибок, когда вероятно, что форму заполнил робот (сообщение + HTTP 403)
		
		// проверяем корретность значений всех полей формы
		//pr($fields);
		foreach ($fields AS $field) 
		{
			if ($field->required && !trim($field->value))
				self::$errors[] = "Не заполненно обязательное поле <b>'$field->label'</b>";
		
		}
		
		$params['email_to'] = trim(val($params['email_to']));
		if(!$params['email_to']) !$params['email_to'] = Admin::$Config->admin_email;
		
		if(!$params['email_to']) 
		{
			self::$errors = array($msg = 'Отправка письма невозможна, так как  администратор сайта не указал адрес получателя в настройках формы связи на странице http://'. $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
			trigger_error($msg, E_USER_WARNING);
		}
		
		// pr(self::$errors);
		
		// проверяем запрос на спам-робота; 
		// делаем эту проверку в последнюю очередь, так как логирование проверок может быть включено
		if(empty(self::$errors))
			if($err=Antispam::error($params['widget_uid'])) 
				self::$errors[] = $err;
		
		if(empty(self::$errors))
		{
			// загружаем файлы из формы, если они переданы
			if(val(self::$params['file_exists']) && $_FILES)
			{
				Files::upload(array(
					'upload_dir'=> FILES_DIR.'/_upload/mailform'
				));
				
				// pr($_POST, $fields);
				
				// подготавливаем для письма ссылки на загруженные файлы 
				if(!empty($_FILES))
				foreach ($fields AS $field)
					if($field->type=='file' && POST($field->name))
					{
						$field->value = 
							//оригинальное имя по-русски
							$_FILES[$field->name][name] 
							// ссылка на загруженный файл на сервере
							.' (ссылка: http://'
							.$_SERVER['HTTP_HOST']
							.$_POST[$field->name]  
							.' )'
							;
						
						
					}					
			}
			
			//pr($fields);
			
			
			// подготавливаем и отправляем письмо
			$params['subject'] = 
				find_not_empty(
					val($params['subject']), 
					'Сообщение с сайта '.strtoupper($_SERVER['HTTP_HOST'])
				);
			
			$mail_template  = View::get_template('mailform/mailform_mail');
			$mail_body		= eval_template($mail_template, $params, array('params'=> $params ));
			
			// pr($mail_body);
			
			$res = Mail::send(array(
				'to'		=> $params['email_to'],
				'from'		=> val($params['email_from'], 
									'Форма связи '
									.strtoupper(str_replace('www.','',
									   $_SERVER['HTTP_HOST']))
									.' <mailform-no-replay@'
										.$_SERVER['HTTP_HOST'])
									  .'>', 
										
				'subject'	=> $params['subject'],
				'body'		=> $mail_body,
			));
		
			if (!$res) 
			{
				self::$errors[] = "Сервер не смог отправить письмо (неизвестаня внутренняя ошибка). Попробуйте отправить позже.";
				
				trigger_error('Сервер не смог отправить письмо на адрес '.$params['email_to'],  E_USER_WARNING );
			}	
		}
		
		
		// если ошибка - сообщаем об этом и возвращаемся к форме
		// ~TODO: проверять наличие шаблона 'mailform_error
		if (self::$errors)
		{
			// подготавливаем сообщение об ошибке
			
			
			$params['error'] = "<div>Ошибка!<br/>".implode("</div><div>",  $params['errors'])."</div>";
			
			$params['error_alert']  = html_alert("Ошибка!\n".implode("\n",  $params['errors']));
			
			
			// pr($params);
		
		}
		else
		{
			// если успех - сообщаем об этом и редиректим на ту же страницу с чистой формой
			// ~TODO: проверять наличие шаблона 'mailform_success'
			echo "
			<noscript><center>
				Спасибо! Ваше послание успешно отправлено.<br/>
				<a href='$_SERVER[REQUEST_URI]' style='color:gray' >вернуться</a>
				<br/><br/>
			</center></noscript>";
			
			echo "
			<script>
				alert('Спасибо! Ваше послание успешно отправлено.');
				document.location='$_SERVER[REQUEST_URI]'
			</script>";
			 
			exit;
		}
		
	}
		
}


